package com.ljx.funchat.chat.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.ljx.funchat.chat.dao.*;
import com.ljx.funchat.chat.domain.entity.*;
import com.ljx.funchat.chat.domain.enums.RoomStatusEnum;
import com.ljx.funchat.chat.domain.enums.RoomTypeEnum;
import com.ljx.funchat.chat.domain.vo.req.ChatMessagePageReq;
import com.ljx.funchat.chat.domain.vo.req.ChatMessageReadReq;
import com.ljx.funchat.chat.domain.vo.req.ChatMessageReq;
import com.ljx.funchat.chat.domain.vo.resp.ChatMessageResp;
import com.ljx.funchat.chat.service.ChatService;
import com.ljx.funchat.chat.service.adapter.MessageAdapter;
import com.ljx.funchat.chat.service.cache.RoomCache;
import com.ljx.funchat.chat.service.strategy.AbstractMsgHandler;
import com.ljx.funchat.chat.service.strategy.MsgHandlerFactory;
import com.ljx.funchat.common.domain.vo.resp.CursorPageBaseResp;
import com.ljx.funchat.common.event.MessageSendEvent;
import com.ljx.funchat.common.utils.AssertUtil;
import com.ljx.funchat.websocket.domain.vo.resp.WSMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class ChatServiceImpl implements ChatService {

    @Autowired
    private RoomDao roomDao;

    @Autowired
    private RoomFriendDao roomFriendDao;

    @Autowired
    private RoomCache roomCache;

    @Autowired
    private RoomGroupDao roomGroupDao;

    @Autowired
    private RoomGroupMemberDao roomGroupMemberDao;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private MessageDao messageDao;

    @Autowired
    private ContactDao contactDao;

    @Override
    public ChatMessageResp sendMsg(Long uid, ChatMessageReq chatMessageReq) {
        // 检查是否可以发送
        check(uid, chatMessageReq);
        // 初步保存聊天信息
        AbstractMsgHandler<?> msgHandler = MsgHandlerFactory.getStrategyNoNull(chatMessageReq.getMsgType());
        Long msgId = msgHandler.checkAndSaveMsg(chatMessageReq, uid);
        // 发送
        applicationEventPublisher.publishEvent(new MessageSendEvent(this, msgId, uid));
        return null;
    }

    private void check(Long uid, ChatMessageReq chatMessageReq) {
        Room room = roomCache.get(chatMessageReq.getRoomId());
        // 单聊
        if (room.getType().equals(RoomTypeEnum.FRIEND.getType())){
            RoomFriend roomFriend = roomFriendDao.getByRoomId(room.getId());
            AssertUtil.notEqual(roomFriend.getStatus(), RoomStatusEnum.ERROR.getStatus(), "您已经被对方拉黑");
            AssertUtil.isTrue(uid.equals(roomFriend.getUid1()) || uid.equals(roomFriend.getUid2()), "您已经被对方拉黑");
        }
        // 群聊
        if (room.getType().equals(RoomTypeEnum.GROUP.getType())){
            RoomGroup roomGroup = roomGroupDao.getByRoomId(room.getId());
            RoomGroupMember roomGroupMember = roomGroupMemberDao.getByGroupId(roomGroup.getId(), uid);
            AssertUtil.isNotEmpty(roomGroupMember, "您已经被移除该群");
        }
    }

    @Override
    public ChatMessageResp getMsgResp(Message message, Long receiveUid, Long uid) {
        return CollUtil.getFirst(getMsgRespBatch(Collections.singletonList(message), receiveUid, uid));
    }

    private List<ChatMessageResp> getMsgRespBatch(List<Message> messages, Long receiveUid, Long uid) {
        if (CollectionUtil.isEmpty(messages)) {
            return new ArrayList<>();
        }

        return MessageAdapter.buildMsgResp(messages, receiveUid, uid);
    }


    @Override
    public CursorPageBaseResp<ChatMessageResp> getChatMsgPage(Long uid, ChatMessagePageReq req) {
        CursorPageBaseResp<Message> messageResp = messageDao.getMessagePage(uid, req);
        if (messageResp.isEmpty()) {
            return CursorPageBaseResp.empty();
        }
        List<ChatMessageResp> msgRespBatch = getMsgRespBatch(messageResp.getList(), null, uid);
        return CursorPageBaseResp.init(messageResp, msgRespBatch);
    }

    @Override
    public void readMsg(Long uid, ChatMessageReadReq readReq) {
        Contact contact = contactDao.getByRoomId(readReq.getRoomId(), uid);
        if (Objects.nonNull(contact)){
            Contact update = new Contact();
            update.setId(contact.getId());
            update.setReadTime(new Date());
            contactDao.updateById(update);
        } else {
            Contact insert = new Contact();
            insert.setReadTime(new Date());
            insert.setRoomId(readReq.getRoomId());
            insert.setUid(uid);
            contactDao.save(insert);
        }

    }
}
